#ifndef _CHECK_H_
#define _CHECK_H_
#include <string>
#include "./../graph/graph.h"
#include "./../grmr/laban.h"
#include <iostream>
#include <sstream>
#include <cstdio>


bool checkConsistency(DAGedges &dag, std::string &errorMessage) {
	//OK so here are the consistency checks I'll do
	//for every product used check if it exists
	//for every item used check if it exists 
	//for every one of those actions, see if the "parameters" of the action exist
	//connect client server
	//request from *provider* to *client*
	//sendplist *client*
	//sendinfo *client* *provider*
	//order *item* *provider* *client*
	//confirm *provider* *client*

	map<string,int> productsIDs;
	map<string,int> clients;
	map<string,int> providers;
	map<string,int> servers;
	map<string,int> items;

	vector <pair <string, string> > providersProducts;
	vector <pair <string, string> > productsItems;

	vector <pair <string, string> > connects;
	vector <pair <string, string> > requests;
	vector <string> sendplists;
	vector <pair <string, string> > sendinfos;
	vector <pair <string, pair <string, string> > > orders;
	vector <pair <string, string> > confirms;

	bool retval = true;
	DAGedges::iterator it = dag.begin();
	while (it != dag.end()) {
		DAGnode PSI;
		PSI = it->first;
		DAGedges::iterator parent = it;			
		it++;			
		while (it != dag.end() && (it->first)==PSI) {					
			it++;
		}

		if(PSI.first == "products") {
			productsIDs[parent->second.first] = 1;
			it--;
			while (it->first == PSI) {
				if (it->second.first != parent->second.first)
					productsItems.push_back(make_pair(parent->second.first,it->second.first));
				it--;
				if (it == parent)
					break;
			}
			while (it != dag.end() && (it->first)==PSI) {					
				it++;
			}
		}		
		if(PSI.first == "client") {
			clients[parent->second.first] = 1;
		}
		if(PSI.first=="provider") {
			it--;	
			providers[parent->second.first] = 1;		
			providersProducts.push_back(make_pair(parent->second.first,it->second.first));
			it++;				
		}
		if(PSI.first == "server") {
			servers[parent->second.first] = 1;
		}
		if(PSI.first == "item") {
			items[parent->second.first] = 1;
		}	

		if(PSI.first == "connect") {
			connects.push_back(make_pair(parent->second.first,(parent+1)->second.first));
		}
		if(PSI.first == "request") {
			requests.push_back(make_pair(parent->second.first,(parent+1)->second.first));
		}
		if(PSI.first == "sendplist") {
			sendplists.push_back(parent->second.first);
		}
		if(PSI.first == "sendinfo") {
			sendinfos.push_back(make_pair(parent->second.first,((parent+1)->second).first));
		}
		if(PSI.first == "order") {
			orders.push_back(make_pair(parent->second.first,make_pair(((parent+1)->second).first,((parent+2)->second).first)));
		}
		if(PSI.first == "confirm") {
			confirms.push_back(make_pair(parent->second.first,((parent+1)->second).first));
		}

	}
	errorMessage = ""; 

	for(int i=0;i<sendplists.size();i++) {
		if(clients.count(sendplists[i])==0) {			
			errorMessage = errorMessage + string("client with ID ") + sendplists[i] + string(" doesn't exist\n");
			retval = false;	
		}		
	}
	for(int i=0;i<providersProducts.size();i++) {
		if(productsIDs.count(providersProducts[i].second)==0) {			
			errorMessage = errorMessage + string("productsid list with ID ") + providersProducts[i].second + string(" doesn't exist\n");
			retval = false;	
		}	
	}
	for(int i=0;i<productsItems.size();i++) {
		if(items.count(productsItems[i].second)==0) {			
			errorMessage = errorMessage + string("item with ID ") + productsItems[i].second + string(" doesn't exist\n");
			retval = false;	
		}
	}		
	for(int i=0;i<connects.size();i++) {
		if(providers.count(connects[i].first)==0 && clients.count(connects[i].first)==0) {
			errorMessage = errorMessage + string("client or provider with ID ") + connects[i].first + string(" doesn't exist\n");
			retval = false;
		}
		if(servers.count(connects[i].second)==0) {
			errorMessage = errorMessage + string("server with ID ") + connects[i].second +  string(" doesn't exist\n");
			retval = false;		
		}
	}
	for(int i=0;i<requests.size();i++) {
		if(providers.count(requests[i].first)==0) {
			errorMessage = errorMessage + string("provider with ID ") + requests[i].first + string(" doesn't exist\n");
			retval = false;
		}
		if(clients.count(requests[i].second)==0) {
			errorMessage = errorMessage + string("server with ID ") + requests[i].second +  string(" doesn't exist\n");
			retval = false;		
		}
	}
	for(int i=0;i<sendinfos.size();i++) {
		if(providers.count(sendinfos[i].first)==0) {
			errorMessage = errorMessage + string("provider with ID ") + sendinfos[i].first +  string(" doesn't exist\n");
			retval = false;
		}
		if(clients.count(sendinfos[i].second)==0) {
			errorMessage = errorMessage + string("client with ID ") + sendinfos[i].first + string(" doesn't exist\n");
			retval = false;
		}
	}	
	for(int i=0;i<orders.size();i++) {
		if(items.count(orders[i].first)==0) {
			errorMessage = errorMessage + string("item with ID ") + orders[i].first +  string(" doesn't exist\n");
			retval = false;
		}
		if(providers.count(orders[i].second.first)==0) {
			errorMessage = errorMessage + string("provider with ID ") + orders[i].second.first + string(" doesn't exist\n");
			retval = false;
		}
		if(clients.count(orders[i].second.second)==0) {
			errorMessage = errorMessage + string("client with ID ") + orders[i].second.second + string(" doesn't exist\n");
			retval = false;
		}
	}	
	for(int i=0;i<confirms.size();i++) {
		if(providers.count(confirms[i].first)==0) {
			errorMessage = errorMessage + string("provider with ID ") + confirms[i].first +  string(" doesn't exist\n");
			retval = false;
		}
		if(clients.count(confirms[i].second)==0) {
			errorMessage = errorMessage + string("client with ID ") + confirms[i].second + string(" doesn't exist\n");
			retval = false;
		}
	}	

	return retval;	
}
#endif

